
package gameserver.taskmanager.tasks;


import gameserver.model.gameobjects.player.Player;
import gameserver.taskmanager.AbstractFIFOPeriodicTaskManager;

/**
 * @author lord_rex and MrPoke
 */
public final class PacketBroadcaster extends AbstractFIFOPeriodicTaskManager<Player> {
    private static final class SingletonHolder {
        private static final PacketBroadcaster INSTANCE = new PacketBroadcaster();
    }

    public static PacketBroadcaster getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private PacketBroadcaster() {
        super(100);
    }

    public static enum BroadcastMode {
        UPDATE_PLAYER_HP_STAT {
            @Override
            public void sendPacket(Creature creature) {
                ((Player) creature).getLifeStats().sendHpPacketUpdateImpl();
            }
        },
        UPDATE_PLAYER_MP_STAT {
            @Override
            public void sendPacket(Creature creature) {
                ((Player) creature).getLifeStats().sendMpPacketUpdateImpl();
            }
        },
        UPDATE_PLAYER_EFFECT_ICONS {
            @Override
            public void sendPacket(Creature creature) {
                ((Player) creature).getEffectController().updatePlayerEffectIconsImpl();
            }
        },
        UPDATE_NEARBY_QUEST_LIST {
            @Override
            public void sendPacket(Creature creature) {
                ((Player) creature).getController().updateNearbyQuestListImpl();
            }
        },

        UPDATE_PLAYER_FLY_TIME {
            @Override
            public void sendPacket(Creature creature) {
                ((Player) creature).getLifeStats().sendFpPacketUpdateImpl();
            }
        },

        BROAD_CAST_EFFECTS {
            @Override
            public void sendPacket(Creature creature) {
                creature.getEffectController().broadCastEffectsImp();
            }
        };

        // TODO: more packets


        private final byte MASK;

        private BroadcastMode() {
            MASK = (byte) (1 << ordinal());
        }

        public byte mask() {
            return MASK;
        }

        protected abstract void sendPacket(Creature creature);

        protected final void trySendPacket(final Creature creature, byte mask) {
            if ((mask & mask()) == mask()) {
                sendPacket(creature);
                creature.removePacketBroadcastMask(this);
            }
        }
    }

    private static final BroadcastMode[] VALUES = BroadcastMode.values();

    @Override
    protected void callTask(Player player) {
        for (byte mask; (mask = player.getPacketBroadcastMask()) != 0;) {
            for (BroadcastMode mode : VALUES) {
                mode.trySendPacket(player, mask);
            }
        }
    }

    @Override
    protected String getCalledMethodName() {
        return "packetBroadcast()";
    }
}
